package dkbta;

import static java.lang.Math.max;
import static java.lang.Math.min;
import dkbta.processing.PlanException;
import dkbta.util.Pair;

public class Tester {
	
	@SuppressWarnings("unused")
	private static Pair<Integer, Integer>[] parsePatientIds(String idRangesStr)	throws PlanException{
	String[] idRanges = idRangesStr.trim().split(" *, *");
	if (idRanges.length == 0){
		throw new PlanException("No patient ids specified");
	}
	@SuppressWarnings("unchecked")
	Pair<Integer, Integer>[] ids = new Pair[idRanges.length];
	for (int j = 0; j < idRanges.length; ++j){
		String[] idRange = idRanges[j].split(" *- *");
		int rangeLen = idRange.length;
		if (rangeLen > 2){
			throw new PlanException("Invalid patient ids: " + idRangesStr);
		}
		try{
			int id1 = Integer.valueOf(idRange[0]);
			int id2 = rangeLen == 2 ? Integer.valueOf(idRange[1]) : id1;
			ids[j] = new Pair<Integer, Integer>(min(id1, id2), max(id1, id2));
		}catch(NumberFormatException e){
			throw new PlanException("Invalid patient ids: " + idRangesStr);
		}
	}
	return ids;
	}
	
	@SuppressWarnings("unused")
	private static String[] parseIntervals(Pair<Integer, Integer>[] ids, int numOfPatients, int numOfUnits){
		int portion = numOfPatients/numOfUnits;
		int res = numOfPatients%numOfUnits;

		String[] patients = new String[numOfUnits];
		int[] idsArray = new int[numOfPatients];
		int currArrayIndx = 0;
		for(int i=0; i<ids.length;i++){
			int first = ids[i].getFirst();
			int second = ids[i].getSecond();
			int len = second - first + 1;
			
			if(len==1){
				idsArray[currArrayIndx] = first;
				currArrayIndx++;
			}
			else{
				for(int j=0; j<len; j++){
					idsArray[currArrayIndx] = first+j;
					currArrayIndx++;
				}
			}
		}
		
		int i = 0;
		int from = 0;
		int to = i<res? portion : portion - 1;
		for(; i<numOfUnits;i++){
			patients[i] = getPatientsAsString(idsArray, from, to);
			System.out.println(patients[i]);
			from = to + 1;
			to = (i+1)<res? (from + portion) : (from + portion - 1);
		}
		return patients;
	}
	
	private static String getPatientsAsString(int[] idsArray, int from, int to){
		int currValue = idsArray[from];
		String resString = "" + currValue;
		boolean isRange = false;
		for(int i=from+1; i<=to; i++){
			if(currValue+1==idsArray[i]){
				currValue=idsArray[i];
				isRange = true;
			}
			else{
				if(isRange){
					resString+="-"+currValue+",";
					isRange=false;
					currValue=idsArray[i];
				}
				else{
					currValue=idsArray[i];
					resString+=",";
				}
				resString+=currValue;
			}
		}
		if(isRange){
			resString+=("-"+currValue);
		}
			
		return resString;
	}
	
	@SuppressWarnings("unused")
	private static int getNumOfPatients(Pair<Integer, Integer>[] ids){
		int numOfPatients = 0;
		for(int i = 0; i < ids.length; i++){
			numOfPatients += (ids[i].getSecond().intValue() - ids[i].getFirst().intValue() + 1);
		}
		return numOfPatients;
	}
	////////////////////////////////////////////////////////////////////////////////////////////////////////
	
	
	private static String allMinusUnit(String all, String unit) throws Throwable{
		Pair<Integer, Integer>[] unitPairs = parsePatientIds(unit);
		Pair<Integer, Integer>[] allPairs = parsePatientIds(all);
		int allLength = getNumOfPatients(allPairs);
		int unitLength = getNumOfPatients(unitPairs);
		int resLength = allLength - unitLength;
		
		int[] resArray = new int[resLength];
		int resIndx = 0;
		for(int i=0; i<allPairs.length; i++){
			int first = allPairs[i].getFirst().intValue();
			int second = allPairs[i].getSecond().intValue();
			for(int j=first; j<=second; j++){
				if(!isPatientIntoRange(unitPairs, j)){
					resArray[resIndx] = j;
					resIndx++;
				}
			}
		}
		return getPatientsAsString(resArray, 0, resLength-1);
	}
	
	private static boolean isPatientIntoRange(Pair<Integer, Integer>[] unitPairs, int patientID) {
		for(int i=0; i<unitPairs.length; i++)
			if(patientID>=unitPairs[i].getFirst().intValue() && patientID<=unitPairs[i].getSecond().intValue())
				return true;
		return false;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////////
	public static void main(String[] args) throws Throwable{
		
		int numOfUnits = 3;
		String[] strings = {"5-10,13,15", "1,3,5,11-22,25,27-32", "19-23,33,45,77-89,98", "1-10"};
				
		
		for(int j=0;j<strings.length;j++){
			
			Pair<Integer, Integer>[] ids = parsePatientIds(strings[j]);
			int numOfPatients = getNumOfPatients(ids);
			System.out.println("\nfrom:\n"+strings[j]+"\nto:");
			
			String[] pts =  parseIntervals(ids, numOfPatients, min(numOfPatients,numOfUnits));

				
			System.out.println(allMinusUnit("1,3,5,11-22,25,27-32", "1,3,5,11-15"));
		
		}
}

}
